package stone926.mods.more_enchantments.mixins;


import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.projectile.PersistentProjectileEntity;
import net.minecraft.item.ArrowItem;
import net.minecraft.item.BowItem;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Hand;
import net.minecraft.util.TypedActionResult;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import stone926.mods.more_enchantments.MoreEnchantmentsMod;
import stone926.mods.more_enchantments.interfaces.IPersistentProjectileEntity;
import stone926.mods.more_enchantments.util.EnchantmentUtil;

import static stone926.mods.more_enchantments.MoreEnchantmentsMod.TRACTION;

@Mixin(BowItem.class)
public abstract class BowItemMixin extends Item {

  public BowItemMixin(Settings settings) {
    super(settings);
  }

  @Shadow
  public abstract TypedActionResult<ItemStack> use(World world, PlayerEntity user, Hand hand);

  @ModifyVariable(method = "onStoppedUsing", at = @At("STORE"))
  private PersistentProjectileEntity onStoppedUsing(PersistentProjectileEntity e, ItemStack stack, World world, LivingEntity user, int remainingUseTicks) {
    IPersistentProjectileEntity arrowEntityWithDraw = (IPersistentProjectileEntity) e;
    arrowEntityWithDraw.setTraction(EnchantmentHelper.getLevel(TRACTION, stack));
    return (PersistentProjectileEntity) arrowEntityWithDraw;
  }

  @Redirect(method = "onStoppedUsing", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/projectile/PersistentProjectileEntity;setVelocity(Lnet/minecraft/entity/Entity;FFFFF)V"))
  public void handleFlash(
    PersistentProjectileEntity persistentProjectileEntity, Entity shooter, float pitch, float yaw, float roll, float speed, float divergence,
    ItemStack stack, World world, LivingEntity user, int remainingUseTicks
  ) {
    int flashLvl = EnchantmentHelper.getLevel(MoreEnchantmentsMod.FLASH, stack);
    if (flashLvl > 0) {
      persistentProjectileEntity.setVelocity(shooter, pitch, yaw, roll, speed * flashLvl * 2, divergence / flashLvl * 1.5F);
    } else {
      persistentProjectileEntity.setVelocity(shooter, pitch, yaw, roll, speed, divergence);
    }
  }

  @Redirect(method = "onStoppedUsing", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;decrement(I)V"))
  private void handleInfinite(ItemStack arrowStack, int amount, ItemStack bowStack, World world, LivingEntity user, int remainingUseTicks) {
    if (!EnchantmentUtil.hasEnchantment(MoreEnchantmentsMod.INFINITE, bowStack)) {
      arrowStack.decrement(amount);
    }
  }

  @Inject(method = "onStoppedUsing", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;spawnEntity(Lnet/minecraft/entity/Entity;)Z"), locals = LocalCapture.CAPTURE_FAILSOFT)
  private void setPickUpType(
    ItemStack stack, World world, LivingEntity user, int remainingUseTicks, CallbackInfo ci,
    PlayerEntity x, boolean y, ItemStack z, int w, float i, boolean j, ArrowItem k, PersistentProjectileEntity persistentProjectileEntity
  ) {
    if (EnchantmentUtil.hasEnchantment(MoreEnchantmentsMod.INFINITE, stack)) {
      persistentProjectileEntity.pickupType = PersistentProjectileEntity.PickupPermission.CREATIVE_ONLY;
    }
  }

}
